

Levels of abstraction
	Raw input (e.g., 'a', 'space', motion) --> bound to...
	Available commands (e.g., 'start jump', 'end jump', 'toggle prone') --> mapped to...
	Actual application of result (e.g., player->jump

IInput detects key 'a' pressed --> InputBinder calls bound event "Player start move left" --> 

Two choices -->
	Read key bindings from settings file and bind a player-control event to each key.
	or
	Read key bindings from settings file and add a player-control event as a listener to each InputEvent

EventManager is low-level
Higher-level code (e.g., InputBinder) does things like bind InputEvents to player-control events
 according to the game settings

class Entity
{
protected:
	std::list<Action> m_Actions;
	
	void exposeAction( String sName );
};

int main()
{
	
	//Declare a new entity type
	EntityAttribute* pFlamable = World::get()->createNewEntityAttribute( "flamable" );
	pFlamable->addAction( "set_on_fire" );
	
	EntityType* pCrateType World::get()->createNewEntityType( "crate", "flamable", "physical", "container" );
	pCrateType->inheritAttribute( 
	pCrateType->addVar( "
	
	Entity* pCrate = World::get()->addEntity( "crate" );
	pCrate.add
	
	Entity e1( "crate" );
	
	
}

class PlayerEntity : public Entity
{
private:
	enum Commands { MOVE_LEFT, MOVE_RIGHT, MOVE_UP, MOVE_DOWN, JUMP, JETPACK, PRONE };
	
public:
	PlayerEntity()
	{
		this->exposeAction( CommandAction( CommandAction::START, MOVE_LEFT ) );
		this->exposeAction( CommandAction( CommandAction::START, MOVE_RIGHT ) );
		this->exposeAction( CommandAction( CommandAction::START, MOVE_UP ) );
		this->exposeAction( CommandAction( CommandAction::START, MOVE_DOWN ) );
		this->exposeAction( CommandAction( CommandAction::START, JUMP ) );
		this->exposeAction( CommandAction( CommandAction::START, JETPACK ) );
		this->exposeAction( CommandAction( CommandAction::START, PRONE ) );
	}
};

class Player
{
	Entity* m_pEntity;
public:
	Player()
	{
		
		EventManager::get()->addRule( InputEvent('A', InputEvent::DOWN),
		    m_pEntity->getAction( CommandAction(
			    CommandAction::START, PlayerEntity::MOVE_LEFT ) ) );
		EventManager::get()->addRule( InputEvent('A', InputEvent::UP),
		    m_pEntity->getAction( CommandAction(
			    CommandAction::STOP, PlayerEntity::MOVE_LEFT ) ) );
		
		EventManager::get()->addRule( InputEvent('space', InputEvent::DOWN),
		    m_pEntity->getAction( CommandAction(
			    CommandAction::START, PlayerEntity::JUMP ) ) );
		EventManager::get()->addRule( InputEvent('space', InputEvent::UP),
		    m_pEntity->getAction( CommandAction(
			    CommandAction::STOP, PlayerEntity::JUMP ) ) );
		
		EventManager::get()->addRule( InputEvent('Z', InputEvent::DOWN),
		    m_pEntity->getAction( CommandAction(
			    CommandAction::TOGGLE, PlayerEntity::PRONE ) ) );
		
	}
	
	void init()
	{
		
		read game settings
		for each 
		
	}
};

//What about a system more in line with a typical Event system -->
// When an event is to be raised, it is done via EventManager::raiseEvent()
// EventManager stores a queue of events raised within the last tick
// Event listeners can be registered with the EventManager, i.e., when event X
//  is raised, call this function (== functor == response == 'Rule').
// Rules could be hard-coded responses to events, or could use the dynamic logic
//  system.
// In this system, Events become nothing more than identifiers with some attached
//  data.

class Event
{
public:
	/*virtual activate()
	{
		EventManager::get()->enqueueEvent( this );
		//NOTE: We could also use something like
		//      EventManager::raiseEvent( const Event& e ) instead, which might
		//      be easier.
	}*/
	
	//No onActivate() !
	// Event 'response' lies in Rules associated with this event in EventManager
	//Derive only to add event data
	
	//TODO: Need some form of identification, as well as corresponding
	//      comparison operators.
	//      (Could almost just replace Events with Strings)
};

//Basically a functor
class Action
{
public:
	virtual void apply() = 0;
};

//An action that calls other actions based on a rule
class Rule : public Action
{
	//Not exactly sure how this works.
	LogicExpression m_Logic;
	
public:
	Rule( LogicExpression& logic ) : m_Logic( logic ) {}
	
	//NOTE: Virtual so that could override with hard-coded logic, but normally
	//      would just use this and a dynamically defined m_Logic expression.
	virtual void invoke()
	{
		//Not exactly sure how this works
		//Need to be able to have multiple expression results, which could be
		// more events to raise, or 
		m_Logic.evaluate();
	}
};



// Ok, here's my thoughts on how this could work. I like the idea of using the
//  logic system for event handling, so that's the basis of this. I thought that
//  if we had a control handler, which would just be a set of rules specifically
//  for input events, we could dynamically interchange them to change the
//  behaviour of fixed input commands.

class RuleSet
{
    std::map<String, Rule*> m_pRules;
public:
    void addRule(String eventName, Rule* pRule);
    bool invokeRules(Event& pEvent); // invokes rules pertaining to this event, returns true if any rules found
}


// This class takes input events and deals with them appropriately
class ControlEventHandler : public RuleSet
{
    Entity* m_pControlledEntity;
    ControlEventHandler* m_pOverride;     // allows controls to be overridden by another handler
public:
    bool invokeControls(InputEvent& pInput) { if(!m_pOverride->invokeControls(pInput)) invokeRules(pInput); }

};

class PlayerEntity : public Entity
{
    ControlEventHandler* m_pHandler;
public:
    PlayerEntity(  ) { ... addVar<bool>("onGround",false); }
};

class Player
{
    PlayerEntity* myEntity;
    // alternatively we could have a ControlEventHandler in Player which allows higher level control options,
    // but by default defers to the myEntity handler
public:
    void handleControls(InputEvent& pInput) { myEntity->getHandler()->invokeControls(pInput); }
};

Rule jumpRule("if object1 is onGround invoke jumpEvent for object1"); // assuming some nice rule parsing function
PlayerEntity playerEntity;
playerEntity.getHandler()->addRule("InputJump", jumpRule);
   ...
player.handleControls(InputJump());





















//NOTE: This is only an outline, not real code to be used
class PlayerEntity : public Entity
{
	//Controls
		start\stop: Left, Right, Up, Down, Jetpack, Shoot, Jump, Crouch
				toggle:     Weapon 1, Weapon 2..., Prone, Use
	
	Properties
		states
				isJetpacking
				isProne
			on-foot
			on-foot + proning = prone
			on-foot + crouching = crouch
			jetpacking
			jetpacking + proning = gliding
			in-vehicle
			
			Derived states
				prone   = (playerState == ON_FOOT) & proning;
				gliding = (playerState == JETPACKING) & proning;
				crouch  = (playerState == ON_FOOT) & crouching;
			
			struct State {
				LogicExpression<int>  iStance = LogicValue<int>( ON_FOOT );
				LogicExpression<bool> bIsCrouching = LogicValue<bool>( false );
				LogicExpression<bool> bIsProne = LogicBoolOperator<'&'>( 
				                                        LogicIfOperator(
														    LogicEqual<int>(
																m_state.iStance, ON_FOOT)) );
			} m_state;
			
			struct Commands {
				bool bProne;
			} m_commands;
			...
			
			enum PlayerState { ON_FOOT, JETPACKING, GLIDING, IN_VEHICLE ... } iState;
			bool bIsProne;
			bool bIsCrouching;
			bool bLeft, bRight, bUp, bDown;
			bool bIsShooting;
			
			bool bIsJumping;
			
			
		actions
			left\right if on-foot = run left\right
			jetpack start if on-foot = change state to jetpacking
			//up if on-foot = jump
			jump if on-foot = jump
			crouch if on-foot + just-landed = roll
			shoot if on-foot or jetpacking or gliding = shoot at cursor
			cursor-move if gliding = rotate to face cursor
			jetpack end if jetpacking = change state to on-foot
			left\right+up\down if jetpacking = jetpack accel left\right+up\down
			jump if jetpacking = jetpack boost?
			...
			
			StartStopAbility ability( { Left, Right, Up, Down, Jetpack, Shoot, Jump, Crouch } );
			bool bLeft, bRight, bUp, bDown, bJetpack, bShoot, bJump, bCrouch;
			InstantAbility ability( { Select weapon 1, Select weapon 2..., Prone, Use } );
			int iWeaponIndex;
			bool bIsProne;
			Action use;
			
			bindKeyDownToEvent( 'A', StartStopAbility( Game::get()->getLocalPlayer(), 
		
		on event ( Ability(begin, "jetpack") ) change "playerState" to JETPACKING
		on event ( Ability(begin, "prone") ) ) if ( "playerState" == ON_FOOT )
		                                         change "isProne" to true
		                                       else if ( "playerState" == JETPACKING )
		                                         change "playerState" to GLIDING
		
		add watcher watchProne to Ability(player, TOGGLE, "prone")
		on event ( Ability(player, TOGGLE, "prone") ) ) toggle "isProne"
		
		in watchProne.onActivate()
		                             
		
		
		all Abilities\Actions will be start-stop.
		Ability( {START, STOP, TOGGLE} );
		bindKeyDownToEvent( 'A', Ability(player, START, "left") );
		bindKeyUpToEvent( 'A', Ability(player, STOP, "left") );
		bindKeyDownToEvent( 'Q', Ability(player, TOGGLE, "prone") );
		
		
		Rule rule( ;
		player->addRule( rule );
		
public:
	
	
	
};
